/*
每⼀个Connection对连接进⾏管理，最终都不可避免需要涉及到应⽤层协议的处理，因此在
Connection中需要设置协议处理的上下⽂来控制处理节奏。但是应⽤层协议千千万，为了降低耦合
度，这个协议接收解析上下⽂就不能有明显的协议倾向，它可以是任意协议的上下⽂信息，因此就需
要⼀个通⽤的类型来保存各种不同的数据结构。
在C语⾔中，通⽤类型可以使⽤void*来管理，但是在C++中，boost库和C++17给我们提供了⼀个通⽤
类型any来灵活使⽤，如果考虑增加代码的移植性，尽量减少第三⽅库的依赖，则可以使⽤C++17特性
中的any，或者⾃⼰来实现。
*/

/*⾸先Any类肯定不能是⼀个模板类，否则编译的时候 Any<int> a,  Any<float>b,需要传类型作
为模板参数，也就是说在使⽤的时候就要确定其类型*/
/*这是⾏不通的，因为保存在Content中的协议上下⽂，我们在定义any对象的时候是不知道他们的协
议类型的，因此⽆法传递类型作为模板参数*/
/*因此考虑Any内部设计⼀个模板容器holder类，可以保存各种类型数据*/
/*⽽因为在Any类中⽆法定义这个holder对象或指针，因为any也不知道这个类要保存什么类型的数
据，因此⽆法传递类型参数*/
/*所以，定义⼀个基类holder，让placehoder继承于holder，⽽Any类保存⽗类指针即可*/
/*当需要保存数据时，则new⼀个带有模板参数的⼦类placehoder对象出来保存数据，然后让Any类中的⽗
类指针，指向这个⼦类对象就搞定了*/
#pragma once
#include<utility>
#include<typeinfo>
#include<cassert>
class Any{
    private:

        class holder{//基类
            public:
                virtual ~holder() {};
                virtual const std::type_info& GetType() = 0;
                virtual holder *Clone() = 0;
        };

        template<typename T>
        class placehoder: public holder{//子类
            public:
                placehoder(const T& data): _data(data){};
                virtual const std::type_info& GetType() override//获取子类保存的数据类型
                {
                    return typeid(T);
                }
                virtual holder *Clone() override//针对当前的对象，克隆出一个新的子类对象
                {
                    return new placehoder<T>(_data);
                }

            public:
                T _data;
        };
        holder *_content;//基类指针，指向具体的子类对象
    public:

        Any& Swap(Any& other)//交换两个Any对象,用于辅助实现赋值运算符
        {
            std::swap(_content, other._content);
            return *this;
        }

        //各种构造
        Any(): _content(nullptr){};
        
        template<typename T>
        Any(const T& data): _content(new placehoder<T>(data)){};
        
        Any(const Any& other)
        {
            if(other._content){//如果有内容，则克隆出一个新的对象
                _content = other._content->Clone();
            }else{
                _content = nullptr;
            }
        }

        //赋值重载
        template<typename T>
        Any& operator=(const T& data)
        {
            Any(data).Swap(*this);//先构造一个临时对象，然后交换内容
            return *this;
        }

        Any& operator=(const Any& other)
        {
            Any(other).Swap(*this);//先构造一个临时对象，然后交换内容
            return *this;
        }

        ///////////////////////////////////////////////////////////////
        template<typename T>
        T *GetData()//获取子类对象保存的数据(传引用)
        {
            assert(_content->GetType() == typeid(T));//断言类型是否正确
            return &((placehoder<T> *)_content)->_data;//强制类型转换成子类对象，获取数据
        }

        ~Any(){delete _content;}
};



